package com.codeerror.demo.ui.fragment;

import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.PagerSnapHelper;
import androidx.recyclerview.widget.RecyclerView;

import com.codeerror.demo.R;
import com.codeerror.demo.adapter.CardWrapperRecyclerAdapter;
import com.codeerror.demo.adapter.WordsListRecyclerAdapter;
import com.codeerror.demo.bean.CardBean;
import com.codeerror.demo.bean.WordsBean;
import com.codeerror.demo.util.DateUtil;
import com.codeerror.demo.util.FindDataUtil;
import com.codeerror.demo.view.SelectDateDialog;
import com.codeerror.demo.view.ShowAddDialog;
import com.codeerror.demo.view.WordsDialog;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.ArrayList;
import java.util.List;

import static com.codeerror.demo.util.FindDataUtil.getWordsData;

public class TodoFragment extends Fragment {
    private TextView tvDate, noTodoCard;
    private RecyclerView rvTodo, rvWords;
    private FloatingActionButton fabAdd;
    private LinearLayout llTodoLoading;
    private CoordinatorLayout coordinatorLayout;

    private WordsListRecyclerAdapter wordsAdapter;
    private CardWrapperRecyclerAdapter cardAdapter;
    private List<WordsBean> nowDayWordsList;
    private List<CardBean> cardList;

    private long curTime;
    private float startX, startY; // 手指按下的起始坐标
    private long firstTime; // 第一次按下tvDate的时间
    private boolean isInLeft = true; // tvDate是否在屏幕的左边

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 5.0以上修改状态栏字体颜色
            getActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        }
        View view = inflater.inflate(R.layout.fragment_todo, container, false);
        initView(view);
        initData();
        initListener();
        return view;
    }

    @SuppressLint("ClickableViewAccessibility")
    private void initListener() {
        // FAB点击事件监听
        fabAdd.setOnClickListener(view -> {
            fabAdd.hide();
            new ShowAddDialog.Builder(getActivity())
                    .setOnAddDialogDismissListener(() -> fabAdd.show())
                    .setOnCreateSuccessListener(cardBean -> {
                        cardList.add(cardBean);
                        cardAdapter.notifyDataSetChanged();
                    }).create().showDialog();
        });
        // 设置日期点击和滑动事件
        tvDate.setOnTouchListener((view, motionEvent) -> {
            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    startX = motionEvent.getRawX();
                    startY = motionEvent.getRawY();
                    firstTime = System.currentTimeMillis();
                    break;
                case MotionEvent.ACTION_MOVE:
                    float dx = motionEvent.getRawX() - startX;
                    float dy = motionEvent.getRawY() - startY;
                    Log.e("Todo", "dx:"+dx+" dy:"+dy);
                    // 禁止CoordinatorLayout的拦截事件
                    coordinatorLayout.requestDisallowInterceptTouchEvent(true);
                    CoordinatorLayout.LayoutParams cl =
                            (CoordinatorLayout.LayoutParams) tvDate.getLayoutParams();
                    // 因为layout_gravity的缘故，需要分两种情况改变左右margin值
                    if ((tvDate.getLeft() + tvDate.getRight()) / 2 >= getScreenWidth() / 2) {
                        // 此时date在屏幕右边
                        if (isInLeft) {
                            // 如果移动之前在左边，更换背景，改变layout_gravity
                            tvDate.setBackgroundResource(R.drawable.bg_todo_right_date_text);
                            isInLeft = false;
                            cl.gravity = Gravity.END;
                        }
                        cl.leftMargin = 0;
                        cl.rightMargin = (int) (getScreenWidth() - tvDate.getRight() - dx);
                    } else {
                        // 此时date在屏幕左边
                        if (!isInLeft) {
                            // 如果移动之前在右边，更换背景，改变layout_gravity
                            tvDate.setBackgroundResource(R.drawable.bg_todo_left_date_text);
                            isInLeft = true;
                            cl.gravity = Gravity.START;
                        }
                        cl.leftMargin = (int) (tvDate.getLeft() + dx);
                        cl.rightMargin = 0;
                    }
                    Log.e("Todo", ""+tvDate.getTop() + dy);
                    cl.topMargin = (int) (tvDate.getTop() + dy);
                    tvDate.setLayoutParams(cl);
                    startX = motionEvent.getRawX();
                    startY = motionEvent.getRawY();
                    break;
                case MotionEvent.ACTION_UP:
                    coordinatorLayout.requestDisallowInterceptTouchEvent(true);
                    if (System.currentTimeMillis() - firstTime <= 200) {
                        // 按下的时间小于500毫秒，此时为点击事件
                        showDateSelectDialog();
                        return true;
                    }
                    // 抬起手指的恢复靠边状态
                    CoordinatorLayout.LayoutParams cl2 =
                            (CoordinatorLayout.LayoutParams) tvDate.getLayoutParams();
                    if ((tvDate.getLeft() + tvDate.getRight()) / 2 >= getScreenWidth() / 2) {
                        // 如果在右边
                        cl2.rightMargin = 0;
                    } else {
                        // 如果在左边
                        cl2.leftMargin = 0;
                    }
                    tvDate.setLayoutParams(cl2);
                    break;
            }
            return true;
        });
    }

    @SuppressLint("SetTextI18n")
    private void initData() {
        // 更新当前的年份和月份
        curTime = System.currentTimeMillis();
        tvDate.setText(DateUtil.getFormattedTime(curTime));
        // 更新卡片列表内容
        cardList = new ArrayList<>();
        updateCardRecyclerData();
        // 获取今日“每日一句”的内容及背景
        nowDayWordsList = new ArrayList<>(getWordsData(curTime));
        // 加载每日一句列表
        LinearLayoutManager manager = new LinearLayoutManager(getActivity());
        manager.setOrientation(RecyclerView.HORIZONTAL);
        wordsAdapter = new WordsListRecyclerAdapter(nowDayWordsList);
        // 设置每日一句点击事件
        wordsAdapter.setOnClickWordsListener((position, type) -> {
            if (type == WordsListRecyclerAdapter.NORMAL_WORDS) {
                // 修改已有的句子的对话框
                showEditWordsDialog(position);
            } else if (type == WordsListRecyclerAdapter.ADD_WORDS) {
                // 创建新的句子的对话框
                showCreateWordsDialog(position);
            }
        });
        rvWords.setLayoutManager(manager);
        rvWords.setAdapter(wordsAdapter);
        // 添加Snap滑动
        PagerSnapHelper snapHelper = new PagerSnapHelper();
        rvWords.setOnFlingListener(null);
        snapHelper.attachToRecyclerView(rvWords);
    }

    /**
     * 更新卡片列表的数据
     */
    private void updateCardRecyclerData() {
        // 获取今日所有待办卡片数据
        cardList.clear();
        cardList.addAll(FindDataUtil.getCountDownData(curTime));
        cardList.addAll(FindDataUtil.getPromiseData());
        cardList.addAll(FindDataUtil.getAnniversaryData());
        cardList.addAll(FindDataUtil.getTodoListData(curTime));
        rvTodo.setVisibility(View.VISIBLE);
        noTodoCard.setVisibility(View.GONE);
        cardAdapter = new CardWrapperRecyclerAdapter(getActivity(), cardList);
        cardAdapter.setOnClickAddTodoListener((todoBsdFragment, todoListTime) -> {
            todoBsdFragment.show(getActivity().getSupportFragmentManager(),
                    String.valueOf(todoListTime));
        });
        rvTodo.setLayoutManager(new LinearLayoutManager(getActivity()));
        rvTodo.setAdapter(cardAdapter);
    }

    /**
     * 展示新建每日一句的对话框
     *
     * @param position 当前点击句子的在Recycler中的位置
     */
    private void showCreateWordsDialog(int position) {
        new WordsDialog.Builder(getActivity())
                .setTime(curTime)
                .setType(WordsListRecyclerAdapter.ADD_WORDS)
                .setDefaultBgId(R.drawable.words_bg_pink)
                .setOnWordsCreateListener(wordsBean -> {
                    wordsBean.save();
                    nowDayWordsList.add(wordsBean);
                    // 注意这个不能用notifyDataInsert(position)
                    // 由于是snap滑动，最后一个View的位置获取会出问题
                    wordsAdapter.notifyDataSetChanged();
                    rvWords.scrollToPosition(position);
                }).create().showDialog();
    }

    /**
     * 展示编辑句子内容的对话框
     *
     * @param position 当前点击句子的在Recycler中的位置
     */
    private void showEditWordsDialog(int position) {
        new WordsDialog.Builder(getActivity())
                .setType(WordsListRecyclerAdapter.NORMAL_WORDS)
                .setHasWordsBean(nowDayWordsList.get(position))
                .setOnWordsCreateListener(wordsBean -> {
                    WordsBean hasWordsBean = nowDayWordsList.get(position);
                    hasWordsBean.setWords(wordsBean.getWords());
                    hasWordsBean.setBgId(wordsBean.getBgId());
                    wordsBean.save();
                    wordsAdapter.notifyItemChanged(position);
                })
                .setOnWordsDeleteListener(() -> {
                    nowDayWordsList.get(position).delete();
                    nowDayWordsList.remove(position);
                    wordsAdapter.notifyDataSetChanged();
                }).create().showDialog();
    }

    /**
     * 展示选择日期的Dialog
     */
    @SuppressLint("SetTextI18n")
    private void showDateSelectDialog() {
        new SelectDateDialog.Builder(getActivity())
                .setCurTime(curTime)
                .setOnSelectDateListener(millis -> {
                    llTodoLoading.setVisibility(View.VISIBLE);
                    noTodoCard.setVisibility(View.GONE);
                    rvTodo.setVisibility(View.GONE);
                    curTime = millis;
                    updateCardRecyclerData();
                    llTodoLoading.setVisibility(View.GONE);
                    // 更新每日一句列表内容
                    nowDayWordsList.clear();
                    nowDayWordsList.addAll(getWordsData(curTime));
                    wordsAdapter.notifyDataSetChanged();
                    // 设置当前日期时间信息
                    tvDate.setText(DateUtil.getFormattedTime(curTime));
                }).create().showDialog();
    }

    private void initView(View view) {
        tvDate = view.findViewById(R.id.tv_todo_date);
        rvTodo = view.findViewById(R.id.rv_todo_list);
        rvWords = view.findViewById(R.id.rv_main_words);
        fabAdd = view.findViewById(R.id.fab_todo_add);
        noTodoCard = view.findViewById(R.id.tv_no_todo_card);
        llTodoLoading = view.findViewById(R.id.ll_todo_loading);
        coordinatorLayout = view.findViewById(R.id.coordinator_main);
    }

    /**
     * 获取屏幕的宽度
     */
    private int getScreenWidth() {
        WindowManager manager = getActivity().getWindowManager();
        DisplayMetrics outMetrics = new DisplayMetrics();
        manager.getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.widthPixels;
    }
}
